#include "UdpWidget.h"
#include "ui_UdpWidget.h"
#include <QHostInfo>

UdpWidget::UdpWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::UdpWidget)
{
    ui->setupUi(this);

    initDataSlot();
}

UdpWidget::~UdpWidget()
{
    delete ui;
}

void UdpWidget::initDataSlot()
{
    if(mUdpSocket == nullptr)
    {
        mUdpSocket = new QUdpSocket(this);
    }

    ui->label_socketState->setText("Socket 状态:");

    QString localIP=getLocalIP();//本机 IP
    this->setWindowTitle (this->windowTitle() +"----本机IP: "+localIP) ;

    ui->spinBox_bindingPort->setMinimum(100);
    ui->spinBox_bindingPort->setMaximum(10000);
    ui->spinBox_bindingPort->setValue(1001);


    ui->spinBox_Targetport->setMinimum(100);
    ui->spinBox_Targetport->setMaximum(10000);
    ui->spinBox_Targetport->setValue(1001);

    ui ->comboTargetIP->addItem(localIP) ;

    connect(mUdpSocket, &QUdpSocket::stateChanged, this, &UdpWidget::onSocketStateChange);

    connect(mUdpSocket, &QUdpSocket::readyRead, this, &UdpWidget::onSocketReadyRead);

    ui->pushButton_bindingPort->setEnabled(true);
    ui->pushButton_unbound->setEnabled(false);
}

QString UdpWidget::getLocalIP()
{
    //获取本机IPv4地址
    QString hostName=QHostInfo::localHostName() ;//本地主机名
    QHostInfo hostInfo=QHostInfo::fromName (hostName) ;

    QString localIP="";
    QList<QHostAddress> addList=hostInfo.addresses () ;
    if (!addList. isEmpty())
    {
        for (int i=0; i <addList.count() ;i++)
        {
            QHostAddress aHost=addList.at(i) ;
            if (QAbstractSocket::IPv4Protocol == aHost. protocol())
            {
                localIP=aHost. toString() ;
                break;
            }
        }
    }

    return localIP;
}

void UdpWidget::onSocketStateChange(QAbstractSocket::SocketState socketState)
{
    switch (socketState)
    {
    case QAbstractSocket::UnconnectedState:
        ui->label_socketState->setText ("socket状态: UnconnectedState") ;
        break;
    case QAbstractSocket::HostLookupState:
        ui->label_socketState->setText ("socket状态: HostLookupState") ;
        break;
    case QAbstractSocket::ConnectingState:
        ui->label_socketState->setText ("socket状态: ConnectingState") ;
        break;
    case QAbstractSocket::ConnectedState:
        ui->label_socketState->setText ("socket状态: ConnectedState") ;
        break;
    case QAbstractSocket::BoundState:
        ui->label_socketState->setText ("socket状态: BoundState") ;
        break;
    case QAbstractSocket::ClosingState:
        ui->label_socketState->setText ("socket状态: ClosingState") ;
        break;
    case QAbstractSocket::ListeningState:
        ui->label_socketState->setText ("socket状态: ListeningState") ;
        break;
    }
}

void UdpWidget::onSocketReadyRead()
{
    //读取收到的数据报
    while (mUdpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram. resize (mUdpSocket->pendingDatagramSize()) ;
        QHostAddress peerAddr;
        quint16 peerPort;
        mUdpSocket->readDatagram (datagram. data(), datagram.size(), &peerAddr, &peerPort) ;
        QString str=datagram.data() ;
        QString peer="[From "+peerAddr. toString() +":" +QString::number (peerPort)+"] ";

        ui->plainTextEdit->appendPlainText (peer+str) ;
    }

}


void UdpWidget::on_sendUnicastMsgBtn_clicked()
{
    //发送单播消息
    QString targetIP = ui->comboTargetIP->currentText(); //目标IP

    QHostAddress  targetAddr (targetIP) ;
    quint16 targetPort=ui->spinBox_Targetport->value() ;//目标port
    QString msg=ui->lineEdit_editMsg->text() ;//发送的消息内容
    QByteArray str=msg. toUtf8() ;

    mUdpSocket->writeDatagram (str, targetAddr, targetPort); //发出数据报

    ui->plainTextEdit->appendPlainText ("[out] "+msg) ;
    ui->lineEdit_editMsg->clear();
    ui ->lineEdit_editMsg->setFocus () ;

}


void UdpWidget::on_SendBroadcastMsgBtn_clicked()
{
    //发送广播消息
    //quint16  targetPort=ui->spinBox_Targetport->value(); //目标端口

    //因为是一台电脑，所以端口不能相同，为了后面的测试效果写死广播目标范围
    quint16 targetPort[5] ={1001,1002,1003,1004,1005};

    QString  msg=ui->lineEdit_editMsg->text () ;
    QByteArray str=msg.toUtf8();

    for(auto port:targetPort){
        mUdpSocket->writeDatagram (str, QHostAddress::Broadcast, port) ;
    }

    ui->plainTextEdit->appendPlainText (" [broadcast] "+msg) ;
    ui->lineEdit_editMsg->clear () ;
    ui ->lineEdit_editMsg->setFocus ();
}


void UdpWidget::on_pushButton_bindingPort_clicked()
{
    //绑定端口
    quint16 port =ui->spinBox_bindingPort->value(); //本机UDP端口
    if (mUdpSocket->bind (port)) //绑定端口成功
    {
        ui->plainTextEdit->appendPlainText("**已成功绑定") ;
        ui->plainTextEdit->appendPlainText("**绑定端口:"+QString::number(mUdpSocket->localPort())) ;
        ui->pushButton_bindingPort->setEnabled(false);
        ui->pushButton_unbound->setEnabled(true);
    }
    else{
        ui->plainTextEdit->appendPlainText("**绑定失败");
    }

}


void UdpWidget::on_pushButton_unbound_clicked()
{
    //解除绑定
    mUdpSocket->abort() ; //解除绑定
    ui->pushButton_bindingPort->setEnabled(true);
    ui->pushButton_unbound->setEnabled(false);
    ui->plainTextEdit->appendPlainText("**已解除绑定") ;
}


void UdpWidget::on_pushButton_cleanText_clicked()
{

}

